import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.Sprite;
import flash.ui.Keyboard;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.filters.GlowFilter;
import haxe.FastList;
import flash.events.MouseEvent;
import flash.net.SharedObject;
import flash.Lib;
import haxe.Log;

import flash.utils.Timer;
import haxe.Timer;
import flash.events.Event;
import flash.display.MovieClip;
import flash.media.SoundChannel;


import Images; 
import Sounds; 
import MovieClips;
import Blob;
import Scene;
import TextArea;
import InstructionPage;
import CreditsPage;
import OptionsPage;
import SoundPlayer;
import PauseMenu;
import Kongregate;
import Logo;
import CustomSprite;

class Main extends Sprite{
private var ground : Int;
private var currentLevel : Int;
private var Scenes : Array<Scene>;
//Because the levels are so similiar i can do this. It's probably be to have a class for each level that inherents from the scence. 
private var Level1 : Scene;

private var State : String;
// private var savedData:SharedObject;
private var ContinueGameButton:Sprite;
private var StartGameButton:Sprite;
private var MainMenuButton:Sprite;
private var InstructionsButton:Sprite;
private var CreditsButton:Sprite;
private var OptionsButton:Sprite;
private var Title:TextField;
private var myLogo : Logo;

private var label1:TextField;
private var Zombie:Sprite;
var myTimer:Timer;
//var music:BackgroundMusic;            
public var Castle:CustomSprite;
var preloader:PreloaderHost;
private var BackgroundImage : Bitmap;
public var Instruction : InstructionPage;
public var Credit: CreditsPage;
public var OptionsMenu : OptionsPage;
var pausePosition:Float;
//             music.play();
var volume:Bool;
var sound:Bool;
var framerate:Int;
var mKeyDown:Array<Bool>;


public function new(){
haxe.remoting.AMFConnection.registerClassAlias("FastListAlias",FastList);
super();
Scenes = [];
getLevelData();

//inPostion,inMoveSpeed,inJumpSpeed,inAttackSpeed,inHealth:Int
initLevels();

//Add Main to Current Flash
flash.Lib.current.addChild(this);
//Create Menu (own Class?)
Title = new TextField();
    
  Title.x = 50; Title.y = 20;
  Title.width = Constants.flashWidth-100; Title.height = Constants.flashHeight;
  Title.multiline = true;
  var myFormat:TextFormat = new TextFormat();
  myFormat.size = 25;
  myFormat.align = TextFormatAlign.CENTER;
  Title.defaultTextFormat = myFormat;
  
  Title.htmlText = "Save The Princess";

  Castle = new CustomSprite();
  Castle.graphics.beginBitmapFill(new CastleMainImage());
  Castle.graphics.drawRect(0, 0, 530,500);
//   Castle.graphics.beginFill(0xFFFFFF);
//   Castle.graphics.lineStyle(1);
//   Castle.graphics.drawRect(0,0,530,500);
  Castle.graphics.endFill();
  Castle.x = 150;Castle.y= 100;

 var txtFormat:TextFormat = new TextFormat();
txtFormat.align = TextFormatAlign.CENTER;

//It seems like there should be a better way to add a bitmap to a Sprite than filling the background with the bitmap. But this works.
StartGameButton = new Sprite();
StartGameButton.graphics.beginBitmapFill(new Flag());
StartGameButton.graphics.drawRect(0, 0, 130 ,230);
StartGameButton.x = 152;
StartGameButton.y = 140;
var StartGameButtonText = new TextField();
StartGameButtonText.htmlText = "<font size='20' color='#000000'>"+"Start Game"+"</font>";
StartGameButtonText.width = 120;
StartGameButtonText.x = 2;
StartGameButtonText.y = 50;
StartGameButtonText.setTextFormat(txtFormat);
StartGameButtonText.selectable = false;
StartGameButtonText.mouseEnabled = false;
StartGameButton.addChild(StartGameButtonText);


StartGameButton.buttonMode = true;
StartGameButton.addEventListener(MouseEvent.CLICK, onStartGameButtonClick);

ContinueGameButton = new Sprite();

ContinueGameButton.graphics.beginBitmapFill(new Flag());
ContinueGameButton.graphics.drawRect(0, 0, 130 ,230);
ContinueGameButton.x = 283;
ContinueGameButton.y = 140;
var ContinueGameButtonText = new TextField();
ContinueGameButtonText.htmlText = "<font size='20'>"+"Continue\nGame"+"</font>";
ContinueGameButtonText.width = 130;
ContinueGameButtonText.x = 0;
ContinueGameButtonText.setTextFormat(txtFormat);
ContinueGameButtonText.y = 50;
ContinueGameButtonText.selectable = false;
ContinueGameButtonText.mouseEnabled = false;
ContinueGameButton.addChild(ContinueGameButtonText);

ContinueGameButton.buttonMode = true;
ContinueGameButton.addEventListener(MouseEvent.CLICK, onContinueGameButtonClick);


InstructionsButton = new Sprite();
InstructionsButton.graphics.beginBitmapFill(new Flag());
InstructionsButton.graphics.drawRect(0, 0, 130 ,230);
InstructionsButton.x = 390;
InstructionsButton.y = 150;

InstructionsButton.buttonMode = true;
InstructionsButton.addEventListener(MouseEvent.CLICK, onInstrutionsButtonClick);

Instruction = new InstructionPage();
Instruction.addEventListener("Back",onInstrutionsBack);

CreditsButton = new Sprite();
CreditsButton.graphics.beginBitmapFill(new Flag());
CreditsButton.graphics.drawRect(0, 0, 130 ,230);
CreditsButton.x = 414;
CreditsButton.y = 140;
var CreditsButtonText = new TextField();
CreditsButtonText.htmlText = "<font size='20' >"+"Credits"+"</font>";
CreditsButtonText.width = 130;
CreditsButtonText.x = 0;
CreditsButtonText.setTextFormat(txtFormat);
CreditsButtonText.y = 50;
CreditsButtonText.selectable = false;
CreditsButtonText.mouseEnabled = false;
CreditsButton.addChild(CreditsButtonText);

CreditsButton.buttonMode = true;
CreditsButton.addEventListener(MouseEvent.CLICK, onCreditsButtonClick);

Credit = new CreditsPage();
Credit.addEventListener("Back",onCreditsBack);


OptionsButton = new Sprite();
OptionsButton.graphics.beginBitmapFill(new Flag());
OptionsButton.graphics.drawRect(0, 0, 130 ,230);
var OptionsButtonText = new TextField();
OptionsButtonText.htmlText = "<font size='20'>"+"Options"+"</font>";
OptionsButtonText.width = 130;
OptionsButtonText.x = 0;
OptionsButtonText.setTextFormat(txtFormat);
OptionsButtonText.y = 50;
OptionsButtonText.selectable = false;
OptionsButtonText.mouseEnabled = false;
OptionsButton.addChild(OptionsButtonText);
OptionsButton.x = 545;
OptionsButton.y = 140;

OptionsButton.buttonMode = true;
OptionsButton.addEventListener(MouseEvent.CLICK, onOptionsButtonClick);

OptionsMenu = new OptionsPage();
OptionsMenu.addEventListener("Back",onOptionsMenuBack);
OptionsMenu.addEventListener("ResetSavedData",onOptionsMenuResetSavedData);
OptionsMenu.addEventListener("VolumeToggle",onOptionsMenuVolumeToggle);
OptionsMenu.addEventListener("SoundEffectsToggle",onOptionsMenuSoundEffectsToggle);
//this.addEventListener(Event.ENTER_FRAME, OnEnter);
myTimer = new Timer(12);
  myTimer.addEventListener("timer", OnEnter);
  myTimer.start();

  label1 = new TextField();
  label1.x = 0; label1.y = 0;
  label1.width = Constants.flashWidth; label1.height = 100;
  label1.autoSize = TextFieldAutoSize.CENTER;

Zombie = new Sprite();
Zombie.graphics.beginBitmapFill(new Menu());
Zombie.graphics.drawRect(0, 0, 46,52);
Zombie.x = 300;
Zombie.y = 75;

MainMenuButton  = new Sprite();
MainMenuButton.graphics.beginBitmapFill(new MainMenu());
MainMenuButton.graphics.drawRect(0, 0, 250 ,48);
MainMenuButton.x = 200;
MainMenuButton.y = 135;
MainMenuButton.buttonMode = true;
MainMenuButton.addEventListener(MouseEvent.CLICK, onMainMenuButtonClick);

//The State Will determine whether to load a level, or show Main Menu, or whatever.  Used in the OnEnterEvent.
//State = "StartGame";
State = "LoadMainMenu";
//music = new BackgroundMusic();
preloader = new PreloaderHost();
BackgroundImage = new Bitmap(new Background());


volume = true;
sound = true;
myLogo = new Logo();
addChild(myLogo);


mKeyDown = [];
stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown );
stage.addEventListener(KeyboardEvent.KEY_UP, OnKeyUp );

//preloader.addEventListener(Event.ENTER_FRAME, OnMovieEnter);
}

public function OnKeyUp (event:KeyboardEvent)
    {
      mKeyDown[event.keyCode] = false;
      //lastUp = event.keyCode;
    }

public function OnKeyDown(event:KeyboardEvent)
   {
      // When a key is held down, multiple KeyDown events are generated.
      // This check means we only pick up the first one.
      if (!mKeyDown[event.keyCode])
      {
         // Store for use in game
         mKeyDown[event.keyCode] = true;
	  //I do this here, because if they hold down P,
	 // it won't pause and unpause constantly.
	  if(mKeyDown[ 77 ] == true)
	  {
	    volume = !volume;
	    Scenes[currentLevel-1].volume = volume;
	    Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
	  }
      }
  }

function loadMenu()
{
  addChild(BackgroundImage);
  addChild(Castle);
  addChild(Title);
  addChild(StartGameButton);
  addChild(ContinueGameButton);
  //addChild(InstructionsButton);
  addChild(CreditsButton);
  addChild(OptionsButton);
}
function removeMenu()
{
  removeChild(Title);
  removeChild(Castle);
  removeChild(StartGameButton);
  removeChild(ContinueGameButton);
  removeChild(BackgroundImage);
  //removeChild(InstructionsButton);
  removeChild(CreditsButton);
  removeChild(OptionsButton);
}

//Change to stat Menu
function loadTryAgainMenu(text:String)
{
  addChild(label1);
  label1.htmlText = "<font size='15'>" + text + "</font>";
  addChild(MainMenuButton);
  addChild(Zombie);
}
function removeTryAgainMenu()
{
 removeChild(label1);
 removeChild(MainMenuButton);
 removeChild(Zombie);
}
function initLevels()
{

//Postion, MoveSpeed, JumpSpeed, AttackSpeed, Health, Bitmap)

}

function OnEnter(e:flash.events.Event)
{
if(State == "StartGame")
   {
    loadCurrentLevel(false);
   }
if(State == "ContinueGame")
   {
    loadCurrentLevel(true);
   }
if(State == "LoadMainMenu")
{
 loadMenu();
 State = "MainMenu";
}
if(State == "MainMenu" )
   {
     return;
   }
if(State == "TryAgain")
  {
    AnimateZombie();
    return;
  }
if(State == "InitLoad")
  {
   
    addChild(preloader);
    preloader.play();
    State = "InitLoading";
  }
if(State == "InitLoading")
   { 
    //Always Playing. Possible error with swfmill
    //Skipping for now.
 
    if(!preloader.playing)
       {
        preloader.stop();
        removeChild(preloader);
        State = "LoadingLogo";
       }

   }
if(State == "LoadingLogo")
  {

     if(!myLogo.play())
     {
       State = "LoadMainMenu";
     }
  }
if(State == "Playing")
   {
    if(Scenes[currentLevel-1] != null)
    {
      if(Scenes[currentLevel-1].running)
      {

      return;
      }        
    }
    loadCurrentLevel(true);
   }
// try
// {
// //             var req:flash.net.URLRequest = new flash.net.URLRequest("http://av.adobe.com/podcast/csbu_dev_podcast_epi_2.mp3");
// //             
// //             Sound.load(req);
// var music = new BackgroundMusic();            
//             music.play();
// }
// catch (err:flash.Error)
// {
// trace(err.message);
// }


}
public function AnimateZombie()
{
var randomNumber = Std.random(24);
if(randomNumber == 1)
  Zombie.x = Zombie.x + 5;
if(randomNumber == 2)
  Zombie.x = Zombie.x - 5;

}

//Loads Level based on Current Level
public function loadCurrentLevel(inContinue:Bool) : Bool
{

  currentLevel = 1;
  Level1 = new Scene(new Background());
  Scenes[currentLevel-1] = Level1;

  State = "Playing";
//Level1.Load();
  Scenes[currentLevel-1].Load(volume,sound,inContinue);
  Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
  // Scenes[currentLevel-1].pauseMenu.renderSoundEffects(sound);
  Scenes[currentLevel-1].addEventListener("VolumeToggle",onSceneVolumeToggle);
  Scenes[currentLevel-1].addEventListener("SoundEffectsToggle",onSceneSoundEffectsToggle);
  Scenes[currentLevel-1].addEventListener("LevelQuit",onLevelQuit);
  Scenes[currentLevel-1].addEventListener("LevelRetry",onLevelRetry);
  
  return true;
}

private function onLevelRetry(event:Event)
{
  removeLevelEventListeners();
  State = "StartGame";
  Scenes[currentLevel-1].unLoad();
}
private function onLevelQuit(event:Event)
{
  removeLevelEventListeners();
  State = "LoadingLogo";
  Scenes[currentLevel-1].unLoad();
}

private function removeLevelEventListeners()
{
  Scenes[currentLevel-1].removeEventListener("VolumeToggle",onSceneVolumeToggle);
  Scenes[currentLevel-1].removeEventListener("SoundEffectsToggle",onSceneSoundEffectsToggle);
  Scenes[currentLevel-1].removeEventListener("LevelQuit",onLevelQuit);
  Scenes[currentLevel-1].removeEventListener("LevelRetry",onLevelRetry);
}
public function getLevelData()
{
  
}
public function removeClip(preloader)
{
 removeChild(preloader);
}
private function onStartGameButtonClick(event:MouseEvent) {
currentLevel = 1;
pausePosition = 0;
removeMenu();
State = "StartGame";
}



private function onContinueGameButtonClick(event:MouseEvent) {


removeMenu();
State = "ContinueGame";
}

private function onMainMenuButtonClick(event:MouseEvent) {
removeTryAgainMenu();
State = "LoadMainMenu";
}
private function onInstrutionsButtonClick(event:MouseEvent) {
removeMenu();
addChild(Instruction);
}

private function onCreditsButtonClick(event:MouseEvent) {
removeMenu();
addChild(Credit);
}

private function onOptionsButtonClick(event:MouseEvent) {
removeMenu();
addChild(OptionsMenu);
OptionsMenu.renderVolume(volume);
OptionsMenu.renderSoundEffects(sound);
}

private function onInstrutionsBack(event:InstructionPageEvent)
{
removeChild(Instruction);
loadMenu();
}

private function onOptionsMenuBack(event:OptionsPageEvent)
{
removeChild(OptionsMenu);
loadMenu();
}
private function onOptionsMenuVolumeToggle(event:OptionsPageEvent)
{
volume = !volume;
OptionsMenu.renderVolume(volume);
Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
}
private function onOptionsMenuSoundEffectsToggle(event:OptionsPageEvent)
{
sound = !sound;
OptionsMenu.renderSoundEffects(sound);
}

private function onSceneVolumeToggle(event:PauseMenuEvent)
{
volume = !volume;
Scenes[currentLevel-1].volume = volume;
Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
}
private function onSceneSoundEffectsToggle(event:PauseMenuEvent)
{
sound = !sound;
Scenes[currentLevel-1].sound = sound;
//Scenes[currentLevel-1].pauseMenu.renderSoundEffects(sound);
}
private function onOptionsMenuResetSavedData(event:OptionsPageEvent)
{
      var savedData = SharedObject.getLocal("GameData");
      savedData.data.Player = null;
      savedData.data.PrincessPosition = null;
      savedData.flush();
}
private function onCreditsBack(event:CreditsPageEvent)
{
removeChild(Credit);
loadMenu();
}

//Couldn't get preloader to work.
	    static function onEnterFrame(event : Event)
	    {
	        Log.trace("Downloaded " + Lib.current.root.loaderInfo.bytesLoaded + " of " + Lib.current.root.loaderInfo.bytesTotal + " bytes");
	 
	        if (Lib.current.root.loaderInfo.bytesLoaded >= Lib.current.root.loaderInfo.bytesTotal)
	        {
	            Lib.current.root.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
	            Log.trace("Preloading finished");
	            Lib.current.gotoAndStop("start");
                  // new Images();
	          var mainInstance:Main = new Main();
	        }
	    }

    static function main() {
// Log.trace("Starting preloader");
  //Lib.current.roott.addEventListener(Event.ENTER_FRAME, onEnterFrame);
try
{
 new Main();
}
catch (err:flash.Error)
{
trace(err.message);

}
      // Create the request object...
//       var loader = new flash.display.Loader();
//       // When the image is ready, instanciate the game class...
//       loader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE,
//           function(_) { new Main(untyped loader.content.bitmapData); });
//       // Fire off the request and wait...
//       loader.load(new flash.net.URLRequest("img/file.gif"));
        //new Main();    
      
	
    }
}